package org.fujay.langchain4jserver.infrastructure.adapter.langchain;

import cn.hutool.core.util.EnumUtil;
import dev.langchain4j.model.chat.ChatModel;
import dev.langchain4j.model.chat.StreamingChatModel;
import dev.langchain4j.model.embedding.EmbeddingModel;
import lombok.RequiredArgsConstructor;
import org.fujay.commons.langchain4j.core.enumd.ModelSupplierEnum;
import org.fujay.commons.langchain4j.core.factory.ModelFactory;
import org.fujay.commons.langchain4j.core.options.LlmOptions;
import org.fujay.langchain4jserver.domain.model.aggregate.Model;
import org.fujay.langchain4jserver.domain.model.service.ModelProviderService;
import org.fujay.langchain4jserver.domain.model.vo.SupplierInfo;
import org.fujay.langchain4jserver.domain.model.vo.TestResult;
import org.springframework.stereotype.Component;

import java.util.Objects;

/**
 * 模型提供者适配器
 */
@Component
@RequiredArgsConstructor
public abstract class ModelAdapterService implements ModelProviderService {

    private final ModelFactory modelFactory;

    @Override
    public ChatModel getChatModel(Model model) {
        validateModel(model, "CHAT");
        LlmOptions options = model.convertToLlmOptions();
        ModelSupplierEnum supplierEnum = getSupplierEnum(model.getSupplier());
        return modelFactory.getModelProvider(supplierEnum).ChatModel(options);
    }

    @Override
    public StreamingChatModel getStreamingChatModel(Model model) {
        validateModel(model, "CHAT");
        LlmOptions options = model.convertToLlmOptions();
        ModelSupplierEnum supplierEnum = getSupplierEnum(model.getSupplier());
        return modelFactory.getModelProvider(supplierEnum).streamingChatModel(options);
    }

    @Override
    public EmbeddingModel getEmbeddingModel(Model model) {
        validateModel(model, "EMBEDDING");
        LlmOptions options = model.convertToLlmOptions();
        ModelSupplierEnum supplierEnum = getSupplierEnum(model.getSupplier());
        return modelFactory.getModelProvider(supplierEnum).embeddingModel(options);
    }

    private void validateModel(Model model, String expectedType) {
        Objects.requireNonNull(model, "模型不可为空");
        if (!expectedType.equalsIgnoreCase(model.getModelType().name())) {
            throw new IllegalArgumentException(
                    "模型类型无效,预期 " + expectedType + ", 实际: " + model.getModelType().name());
        }
        if (!model.isEnabled()
                || model.getConnectionStatus().lastTestResult() != TestResult.SUCCESS) {
            throw new IllegalArgumentException("模型未生效或未通过连通性测试");
        }

    }

    private ModelSupplierEnum getSupplierEnum(SupplierInfo supplierInfo) {
        ModelSupplierEnum supplierEnum =
                EnumUtil.getBy(ModelSupplierEnum::getCode, supplierInfo.supplierCode());
        if (supplierEnum == null) {
            throw new IllegalArgumentException("不支持的模型厂商: " + supplierInfo.supplierCode());
        }
        return supplierEnum;
    }
}
